package com.example.touch;

import java.security.PublicKey;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.andengine.engine.Engine;
import org.andengine.engine.handler.timer.ITimerCallback;
import org.andengine.engine.handler.timer.TimerHandler;
import org.andengine.entity.IEntity;
import org.andengine.entity.IEntityFactory;
import org.andengine.entity.modifier.AlphaModifier;
import org.andengine.entity.modifier.MoveModifier;
import org.andengine.entity.modifier.MoveXModifier;
import org.andengine.entity.modifier.MoveYModifier;
import org.andengine.entity.modifier.ParallelEntityModifier;
import org.andengine.entity.modifier.ScaleModifier;
import org.andengine.entity.modifier.SequenceEntityModifier;
import org.andengine.entity.particle.ParticleSystem;
import org.andengine.entity.particle.emitter.PointParticleEmitter;
import org.andengine.entity.particle.emitter.RectangleParticleEmitter;
import org.andengine.entity.particle.initializer.AlphaParticleInitializer;
import org.andengine.entity.particle.initializer.ColorParticleInitializer;
import org.andengine.entity.particle.initializer.GravityParticleInitializer;
import org.andengine.entity.particle.initializer.VelocityParticleInitializer;
import org.andengine.entity.particle.modifier.AlphaParticleModifier;
import org.andengine.entity.particle.modifier.ColorParticleModifier;
import org.andengine.entity.particle.modifier.ExpireParticleInitializer;
import org.andengine.entity.particle.modifier.IParticleModifier;
import org.andengine.entity.particle.modifier.RotationParticleModifier;
import org.andengine.entity.particle.modifier.ScaleParticleModifier;
import org.andengine.entity.primitive.Line;
import org.andengine.entity.primitive.Rectangle;
import org.andengine.entity.scene.CameraScene;
import org.andengine.entity.scene.Scene;
import org.andengine.entity.sprite.AnimatedSprite;
import org.andengine.entity.sprite.Sprite;
import org.andengine.entity.text.Text;
import org.andengine.opengl.vbo.VertexBufferObjectManager;
import org.andengine.util.color.Color;
import org.andengine.util.math.MathUtils;
import org.andengine.util.modifier.IModifier;

import com.example.fruit.GameActivity;
import com.example.fruitpool.Boom;
import com.example.fruitpool.BoomPool;
import com.example.fruitpool.Fruit;
import com.example.fruitpool.FruitPool;
import com.example.fruitpool.Point;
import com.example.fruitpool.Pool;
import com.example.fruitpool.Pool.PoolObjectFactory;
import com.example.input.Input.TouchEvent;
import com.example.manager.ResourcesManager;
import com.example.manager.SceneManager;
import com.example.scene.GameScene;
import com.example.scene.TimerMode;
import com.example.scene.ResultScene;

import android.os.Handler;
import android.util.Log;
import android.view.MotionEvent;
import android.view.animation.ScaleAnimation;


public class MultiTouchHandlerForTimeMode implements TouchHandler {

	public boolean[] isTouched = new boolean[10];
	public int[] touchX = new int[10];
	public int[] touchY = new int[10];
	Pool<TouchEvent> touchEventPool;
	List<TouchEvent> touchEvents = new ArrayList<TouchEvent>();
	List<TouchEvent> touchEventsBuffer = new ArrayList<TouchEvent>();
	private static MultiTouchHandlerForTimeMode instance;
	TimerMode mScene;
	ResourcesManager resourcesManager;
	VertexBufferObjectManager vbom;
	public MultiTouchHandlerForTimeMode(ResourcesManager resourcesManager, VertexBufferObjectManager vbom, Scene mScene) {
		this.mScene = (TimerMode) mScene;
		this.resourcesManager = resourcesManager; 
		this.vbom = vbom;
		PoolObjectFactory<TouchEvent> factory = new PoolObjectFactory<TouchEvent>() {
			public TouchEvent createObject() {
				return new TouchEvent();
			}
		};
		touchEventPool = new Pool<TouchEvent>(factory, 100);

		this.mScene.setOnSceneTouchListener(this);

	}
	
	public boolean isTouchDown(int pointer) {
		synchronized (this) {
			if (pointer < 0 || pointer >= 20)
				return false;
			else
				return isTouched[pointer];
		}
	}

	public int getTouchX(int pointer) {
		synchronized (this) {
			if (pointer < 0 || pointer >= 20)
				return 0;
			else
				return touchX[pointer];
		}
	}

	public int getTouchY(int pointer) {
		synchronized (this) {
			if (pointer < 0 || pointer >= 20)
				return 0;
			else
				return touchY[pointer];
		}
	}

	public List<TouchEvent> getTouchEvents() {
		synchronized (this) {
			int len = touchEvents.size();
			for (int i = 0; i < len; i++)
				touchEventPool.free(touchEvents.get(i));
			touchEvents.clear();
			touchEvents.addAll(touchEventsBuffer);
			touchEventsBuffer.clear();
			return touchEvents;
		}
	}

	static int ii = 0;
	StringBuilder builder = new StringBuilder();
	int x1, y1, x2, y2;
	// com.example.multitouchexample1.Point currPoint, prevPoint,currPoint1,
	// prevPoint1 = null;
	Point[] currPoint = new Point[10]; 
	Point[] prevPoint = new Point[10];
	Line line;
	int x1Convert = 0, y1Convert = 0, x2Convert = 0, y2Convert = 0; 
	
	public void convertTouch(int x1, int y1, int x2, int y2)
	{
	//	float wRate = (float) (1.0*CAMERA_WIDTH/width);
		//float hRate = (float) (1.0*CAMERA_HEIGHT/height);
		//float wRate = (float) (1.0*width/CAMERA_WIDTH);
		//float hRate = (float) (1.0*height/CAMERA_HEIGHT);
		
		x1Convert = (int) (x1*resourcesManager.wRate);
		y1Convert = (int) (y1*resourcesManager.hRate);
		x2Convert = (int) (x2*resourcesManager.wRate);
		y2Convert = (int) (y2*resourcesManager.hRate);
		
		Log.d("inconvert", x1+"->"+x1Convert+":"+y1+"->"+y1Convert);
	}
	boolean k=true;
	Boom boom;
	public int scorex=0;
	boolean checkx2=false;
	@Override
	public boolean onSceneTouchEvent(Scene pScene,org.andengine.input.touch.TouchEvent pSceneTouchEvent) {
		synchronized (this) {
			int action = pSceneTouchEvent.getAction() & MotionEvent.ACTION_MASK;//get action mouse
			int pointerIndex = (pSceneTouchEvent.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
			// int pointerId = pSceneTouchEvent.getPointerId(pointerIndex);
			int pointerId = pSceneTouchEvent.getMotionEvent().getPointerId(pointerIndex);
			// int pointerId = pSceneTouchEvent.getPointerID();
			Log.d("pointerId:", pointerId+"");
			Log.d("pointerIndex:", pointerIndex+"");
			TouchEvent touchEvent;

			switch (action) {
			case MotionEvent.ACTION_DOWN:
			case MotionEvent.ACTION_POINTER_DOWN:
				touchEvent = touchEventPool.newObject();
				touchEvent.type = TouchEvent.TOUCH_DOWN;
				touchEvent.pointer = pointerId;
				touchEvent.x = touchX[pointerId] = (int) pSceneTouchEvent.getMotionEvent().getX(pointerIndex);
				touchEvent.y = touchY[pointerId] = (int) pSceneTouchEvent.getMotionEvent().getY(pointerIndex);
				isTouched[pointerId] = true;
				touchEventsBuffer.add(touchEvent);
				currPoint[pointerId] = new Point();
				currPoint[pointerId].x = (int) pSceneTouchEvent.getMotionEvent().getX(pointerIndex);
				currPoint[pointerId].y = (int) pSceneTouchEvent.getMotionEvent().getY(pointerIndex);
				Log.d("ACTION_POINTER_DOWN->pointerId:", pointerId+"");
				break;

			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_POINTER_UP:
			case MotionEvent.ACTION_CANCEL:
				touchEvent = touchEventPool.newObject();
				touchEvent.type = TouchEvent.TOUCH_UP;
				touchEvent.pointer = pointerId;
				touchEvent.x = touchX[pointerId] = (int) pSceneTouchEvent.getMotionEvent().getX(pointerIndex);
				touchEvent.y = touchY[pointerId] = (int) pSceneTouchEvent.getMotionEvent().getY(pointerIndex);
				isTouched[pointerId] = false;
				touchEventsBuffer.add(touchEvent);
				// mScene.particleSystem.setParticlesSpawnEnabled(false);
				// hideAll();
				Log.d("ACTION_POINTER_UP->pointerId:", pointerId+"");
				k=true;
				//line.detachSelf();
				//mScene.detachChild(line);			
				break; 
 
			case MotionEvent.ACTION_MOVE:
				int pointerCount = pSceneTouchEvent.getMotionEvent().getPointerCount();
				Log.d("ACTION_MOVE->pointerCount", pointerCount+"");
				for (int i = 0; i < pointerCount; i++) {
					try {
						pointerIndex = i;
						pointerId = pSceneTouchEvent.getMotionEvent().getPointerId(pointerIndex);
						touchEvent = touchEventPool.newObject();
						touchEvent.type = TouchEvent.TOUCH_DRAGGED;
						touchEvent.pointer = pointerId;
						touchEvent.x = touchX[pointerId] = (int) pSceneTouchEvent.getMotionEvent().getX(pointerIndex);
						touchEvent.y = touchY[pointerId] = (int) pSceneTouchEvent.getMotionEvent().getY(pointerIndex);
						touchEventsBuffer.add(touchEvent);
						//Log.d("pointerCount:"+i, pointerId + ":" + touchEvent.x + ":"+ touchEvent.y);
						prevPoint[pointerId] = new Point();
						prevPoint[pointerId].x = (int) pSceneTouchEvent.getMotionEvent().getX(pointerIndex);

						// currPoint.x =
						// MultiTouchExample.CAMERA_WIDTH*currPoint.x/MultiTouchExample.getSharedInstance().width;
						prevPoint[pointerId].y = (int) pSceneTouchEvent.getMotionEvent().getY(pointerIndex);
						try {
							convertTouch(prevPoint[pointerId].x, prevPoint[pointerId].y,currPoint[pointerId].x, currPoint[pointerId].y);	
						} catch (Exception e) {
							;
						}
						
						//line = new Line(currPoint[pointerId].x, currPoint[pointerId].y, prevPoint[pointerId].x, prevPoint[pointerId].y, activity.getVertexBufferObjectManager());
						line = new Line(x2Convert,y2Convert,x1Convert,y1Convert,vbom);
						line.setLineWidth(3);
						line.setAlpha(1);
						/*Sprite face;
						face = new Sprite(x2Convert,y2Convert, resourcesManager.streak_region,vbom);
						mScene.attachChild(face);*/
						if(k){
							resourcesManager.playSoundWind();
							k=false;
						}
						{								
							Log.d("countboom", TimerMode.boomList.size() + "");
							final Iterator<Boom> booms = TimerMode.boomList.iterator();
							
							// iterating over the targets
							while (booms.hasNext()) {	
								boom = booms.next();
								if (boom.sprit.collidesWith(line)) {	
									int s = Integer.parseInt(mScene.score);
									if (s < 10)
										s = 0;
									else ///boom-10
										s -= 10;
									mScene.score=s+"";
									loadcong10(1,boom.sprit.getX()+boom.sprit.getWidth()/2+10,boom.sprit.getY()+boom.sprit.getHeight()/2);
									mScene.setTextChange();
									BoomPool.sharedBoomPool().onHandleRecycleItem(boom);
									//targets.remove();
									
									pScene.detachChild(boom.sprit);
									booms.remove();
									break;
								}
							}
							
							Iterator<Fruit> targets = TimerMode.fruitList.iterator();
							Fruit _target;
							while (targets.hasNext()) {
								
								_target = targets.next();
								Log.d("fruit:", _target.sprit.getX()+":"+_target.sprit.getY());
								if (_target.sprit.collidesWith(line)) {
									synchronized (_target) {
										resourcesManager.playSoundSlice();
									}
									createExplosion(_target.sprit.getX()+_target.sprit.getWidth()/2,_target.sprit.getY()+_target.sprit.getHeight()/2,_target.sprit.getParent());
									// removeSprite(_target, targets);
									String score = mScene.score;
									int s = Integer.parseInt(score);							
									if(!checkx2)
									{
										s++;
										mScene.score = s+"";
										Log.d("posee", mScene.score);
										mScene.setTextChange();
									}
									else{
										scorex++;
										mScene.scorex2 = scorex+"";
										Log.d("posee", mScene.score);
										mScene.textx2.setPosition((x2sprite.getX()+x2sprite.getWidth()/2)-mScene.textx2.getWidth()/2, 20);
										mScene.setTextScoreX2();
									}
									
									FruitPool.sharedFruitPool().onHandleRecycleItem(_target);
									//targets.remove();
									
									pScene.detachChild(_target.sprit);
									targets.remove();
									//mScene.detachChild(tar)
									// fail();
									break;
								  
								}
							}
							Iterator<Fruit> targetspecs = TimerMode.specList.iterator();
							Fruit _targetspecs;
							// iterating over the targets
							while (targetspecs.hasNext()) {
								_targetspecs = targetspecs.next();
								if (_targetspecs.spritspec.collidesWith(line)) {
									
									synchronized (_targetspecs) {
										resourcesManager.playSoundSlice();
									}
									String score = mScene.score;
									int s = Integer.parseInt(score);
									switch (Integer.valueOf(_targetspecs.id)) {
									case 0://bananafreeze_region
										mScene.loadFreezeImg();
										waitingBananaCold();
										break;
									case 1://bananafrenzy_region
										mScene.loadFrenzyImg();
										mScene.TimerTextStagger();
										break;
									case 2://bananax2_region
										
										if(!checkx2){
											timeBananaX2=7;
											mycount();
											loadscorex2();
										}else{
											int remaning=timeBananaX2-co;
											timeBananaX2 =remaning+7;
										}
										
										checkTime++;
										break;
									case 3://boom+10
										s+=10;
										mScene.score=s+"";
										loadcong10(0,_targetspecs.spritspec.getX()+_targetspecs.spritspec.getWidth()/2+10,_targetspecs.spritspec.getY()+_targetspecs.spritspec.getHeight()/2);
										mScene.setTextChange();
										break;
									default:
										break;
									}
									Log.d("possssss","_targetspecs");
									FruitPool.sharedFruitPool().onHandleRecycleItemSpec(_targetspecs);
					
									pScene.detachChild(_targetspecs.spritspec);
									targetspecs.remove();
									break;
								  
								}
							}
						} 
						currPoint[pointerId] = prevPoint[pointerId];
					} catch (Exception e) {
						//Log.d("pos", e.getMessage());
					}
					
				}
				break;
			}
			// Log.d("touch", "Asd");
			// updateTextView();
			return true;
		}
		
	}

	
	TimerHandler countCheckTimer;
	int coCheckTimer=0;
	public void waitingBananaCold()
	{
		mScene.t.mPause=true;
		mScene.checkTimer=true;
		countCheckTimer=new TimerHandler(0.1f, true, new ITimerCallback() {
				
				@Override
				public void onTimePassed(TimerHandler pTimerHandler) {
					// TODO Auto-generated method stub
					countCheckTimer.setTimerSeconds(1);
					coCheckTimer++;
					if(coCheckTimer==8){
						mScene.unloadFreezeImg();
						coCheckTimer=0;
						mScene.checkTimer=false;
						mScene.t.mPause=false;
						countCheckTimer.setAutoReset(false);
						resourcesManager.engine.unregisterUpdateHandler(countCheckTimer);
					}
				}
			});
			resourcesManager.engine.registerUpdateHandler(countCheckTimer);
	}
	
	TimerHandler count;
	boolean hidex2;
	int co=0;
	int checkTime=0;
	int timeBananaX2;
	public void mycount()
	{
		checkx2=true;
		count=new TimerHandler(0.1f, true, new ITimerCallback() {
			
			@Override
			public void onTimePassed(TimerHandler pTimerHandler) {
				// TODO Auto-generated method stub
				count.setTimerSeconds(1);
				Log.d("checkx2",co+"");
				co++;
				if(co==timeBananaX2){
					co=0;
					checkx2=false;
					mScene.detachChild(mScene.textx2);
					new Runnable() {
						
						@Override
						public void run() {
							// TODO Auto-generated method stub
							MoveXModifier mod=new MoveXModifier(0.5f, x2sprite.getX(), -100){

								@Override
								protected void onModifierFinished(
										IEntity pItem) {
									// TODO Auto-generated method stub
									super.onModifierFinished(pItem);
									//mScene.detachChild(x2);
									MoveYModifier move=new MoveYModifier(0.5f, mScene.text.getY(), 10);
									mScene.text.registerEntityModifier(move);
								}
								
							};
							x2sprite.registerEntityModifier(mod);

						}
					}.run();
					//x2sprite.setVisible(false);
					count.setAutoReset(false);
					resourcesManager.engine.unregisterUpdateHandler(count);
				}
			}
		});
		resourcesManager.engine.registerUpdateHandler(count);
	}
	
	public void mycount1()
	{
		count=new TimerHandler(0.1f, true, new ITimerCallback() {
			
			@Override
			public void onTimePassed(TimerHandler pTimerHandler) {
				// TODO Auto-generated method stub
				count.setTimerSeconds(1);
				Log.d("checkx2",co+"");
				co++;
				if(co==5){
					co=0;
					checkx2=false;
					hidex2=true;
					/*AlphaModifier alpah=new AlphaModifier(0.1f, 1, 0);
					x2sprite.registerEntityModifier(alpah);*/
					//x2sprite.setVisible(false);
					count.setAutoReset(false);
					resourcesManager.engine.unregisterUpdateHandler(count);
				}
			}
		});
		resourcesManager.engine.registerUpdateHandler(count);
	}
	Sprite textmuoi;
	public void loadcong10(int type,final float posX, final float posY) {
		if(type==0){
			textmuoi = new Sprite(posX + 10, posY,
				resourcesManager.cong10_region, vbom);
		}else
		{
			textmuoi = new Sprite(posX + 10, posY,
					resourcesManager.tru10_region, vbom);
		}
		ScaleModifier scale = new ScaleModifier(0.9f, 0, 1);
		AlphaModifier alpha=new AlphaModifier(0.1f, 1, 0);
		MoveModifier move=new MoveModifier(1f, posX, mScene.text.getX(), posY,  mScene.text.getY());
		
		textmuoi.registerEntityModifier(new SequenceEntityModifier(scale,move,alpha));
		mScene.attachChild(textmuoi);
		
	}
	
	Sprite x2sprite;
	public void loadscorex2()
	{
		MoveYModifier move=new MoveYModifier(0.5f, mScene.text.getY(), -50){

			@Override
			protected void onModifierFinished(IEntity pItem) {
				// TODO Auto-generated method stub
				super.onModifierFinished(pItem);
				x2sprite = new Sprite(-100,10,95,95,
						resourcesManager.x2_region, vbom);
				MoveXModifier mod=new MoveXModifier(0.3f, x2sprite.getX(), 10){

					@Override
					protected void onModifierFinished(
							IEntity pItem) {
						// TODO Auto-generated method stub
						super.onModifierFinished(pItem);
						
						ScaleModifier scale=new ScaleModifier(1f, 0, 1);
						AlphaModifier alpha=new AlphaModifier(1f, 0, 1);
						mScene.textx2.setVisible(true);
						mScene.textx2.registerEntityModifier(new ParallelEntityModifier(scale,alpha));
						mScene.attachChild(mScene.textx2);
					}
					
				};
				x2sprite.registerEntityModifier(mod);
				mScene.attachChild(x2sprite);
			}
			
		};
		
		mScene.text.registerEntityModifier(move);
		
	}
	private void createExplosion(final float posX, final float posY,final IEntity target) {
		int mNumPart = 15;
		int mTimePart = 2;
		
		PointParticleEmitter particleEmitter = new PointParticleEmitter(posX,posY);
		IEntityFactory<Sprite> recFact = new IEntityFactory<Sprite>() {
			@Override
			public Sprite create(float pX, float pY) {
				Sprite rect = new Sprite(pX, pY, resourcesManager.star_region, vbom);
				return rect;
			}

		};
		final ParticleSystem<Sprite> particleSystem = new ParticleSystem<Sprite>(recFact, particleEmitter, 500, 500, mNumPart);
		particleSystem.addParticleInitializer(new VelocityParticleInitializer<Sprite>(-50, 50, -50, 50));
		particleSystem.addParticleModifier(new AlphaParticleModifier<Sprite>(0,0.6f * mTimePart, 1, 0));
		particleSystem.addParticleModifier(new RotationParticleModifier<Sprite>(0,mTimePart, 0, 360));

		target.attachChild(particleSystem);
		target.registerUpdateHandler(new TimerHandler(mTimePart,
				new ITimerCallback() {
					@Override
					public void onTimePassed(final TimerHandler pTimerHandler) {
						particleSystem.detachSelf();
						target.sortChildren();
						target.unregisterUpdateHandler(pTimerHandler);
					}
				}));
	}
}
